<template>
	<view class="treeSelect">
		<view class="header">
			<view class="search-box">
				<view class="search-input" v-if="searchIf">
					<uni-easyinput prefixIcon="search" v-model="searchValue" placeholder="搜索" :inputBorder="false"
						:styles="searchStyles" />
				</view>
				<view class="search-btn">
					<button type="primary" class="mini-btn" size="mini" @click="confirmSearch">搜索</button>
				</view>
			</view>
			<view class="title">
				<scroll-view scroll-x style="width: 100%;white-space: nowrap;" :scroll-left="scrollLeft">
					<view class="inline-item dri" />
					<view v-for="(item, index) in tree_stack" class="inline-item" :key="index">
						<view class="inline-item" v-if="index == 0" @click="backTree(item, -1)">
							<text :class="[(isActive(index) && !isre) ? 'none' : 'active']">全部</text>
						</view>
						<view v-if="index == 0 && isre" @click="backTree(item, -2)"
							:class="[(index == tree_stack.length - 1 && isre) ? 'none' : 'active', 'inline-item']">
							<i class="iconfont icon-z043 iconclass" />
							搜索结果
						</view>
						<view class="inline-item" @click="backTree(item, index)" v-if="index != 0">
							<i class="iconfont icon-z043 iconclass" />
							<text :class="isActive(index) ? 'none inline-ite' : 'active'">
								{{ item[props.options.label] }}
							</text>
						</view>
					</view>
					<view class="inline-item dri" />
				</scroll-view>
			</view>
		</view>

		<view class="container-list">
			<uni-list>
				<uni-list-item v-for="(item, index) in tree" :key="index" :title="item[props.options.label]"
					:showArrow="Boolean(item.children.length)" @click="handleClick(item, index)" :clickable="true">
					<template #header>
						<view class="list-item" v-show="isCheck">
							<view class="checkbox" v-if="props.options.multiple" @click.stop="handleClick(item, -1)">
								<span v-if="isSelect(item)">
									<i v-if="item.bx && newCheckList.length != 0" class="iconfont icon-banxuanzhongshousuo1-shi icons" />
									<i v-else class="iconfont icon-xuanzhong txt icon-selected" />
								</span>
								<i v-else-if="item.qx" class="iconfont icon-xuanzhong txt icon-selected" />
								<i v-else-if="item.bx" class="iconfont icon-banxuanzhongshousuo1-shi icons" />
								<i style="color: #b8b8b8;" v-else class="iconfont icon-weixuanzhong txt" />
							</view>
							<view class="checkbox"
								v-else-if="(props.options.nodes ? Boolean(item.children.length) ? true : false : true)"
								@click.stop="handleClick(item, -1)">
								<i v-if="radioSelect(item)" class="txt iconfont icon-selected" />
								<i style="color: #b8b8b8;" v-else class="txt iconfont icon-weixuanzhong1" />
							</view>
						</view>
					</template>
				</uni-list-item>
			</uni-list>
		</view>
		<view class="btn">
			<button type="primary" @click="backConfirm" style="height: 40px;font-size: 16px;width: 50%;">确认</button>
		</view>
	</view>
</template>

<script setup>
import { ref, reactive, computed, nextTick, h } from 'vue'
const props = defineProps({
	treeNone: {
		type: Array,
		default: () => {
			return []
		}
	},
	checkList: {
		type: Array,
		default: () => {
			return []
		}
	},
	keyValue: {
		type: String,
		default: 'id'
	},
	searchIf: {
		type: Boolean,
		default: true
	},
	isCheck: true,
	checkList: {
		type: Array,
		default: () => []
	},
	parentList: {
		type: Array,
		default: () => []
	},
	options: {
		type: Object,
		default: () => {
			return {
				label: 'name',
				children: 'children',
				multiple: false,
				checkStrictly: false //不关联
			}
		}
	}
})

const searchStyles = {
	backgroundColor: '#f2f2f2',
	height: '35px'
}

const catchTreeNone = JSON.parse(JSON.stringify(props.treeNone)),
	tree = ref(props.treeNone),
	newCheckList = ref(props.checkList),
	tree_stack = ref([1]),
	nodePathArray = ref([]),
	searchResult = ref([]),
	scrollLeft = ref(999),
	oldNum = ref(0),
	newNum = ref(0),
	isre = ref(false)
const emit = defineEmits(['sendValue'])
// 初始化
const initComponent = () => {
	if (newCheckList.value.length !== 0) {
		if (props.options.multiple) {
			if (props.options.checkStrictly) {
				checkAllChoose();
			}
		} else {
			getNodeRoute(catchTreeNone, newCheckList.value[0][props.keyValue])
			let arr = nodePathArray.value.reverse()
			if (arr.length == 0) return
			tree_stack.value = tree_stack.value.concat(arr);
			tree.value = tree_stack.value[tree_stack.value.length - 1].children;
		}
	}
	console.log(props.options)
}
initComponent()
// (tree为目标树，targetId为目标节点id)
function getNodeRoute(tree, targetId) {
	for (let index = 0; index < tree.length; index++) {
		if (tree[index].children) {
			let endRecursiveLoop = getNodeRoute(tree[index].children, targetId)
			if (endRecursiveLoop) {
				nodePathArray.value.push(tree[index])
				return true
			}
		}
		if (tree[index][props.keyValue] === targetId) {
			return true
		}
	}
}

const radioSelect = computed(() => {
	return (item) => {
		const list = newCheckList.value
		return list.length > 0 && item[props.keyValue] == list[0][props.keyValue]
	}
})
const isActive = computed(() => {
	return (index) => {
		return index === tree_stack.value.length - 1
	}
})
const isSelect = computed(() => {
	return (item) => {
		const checkList = newCheckList.value
		if (checkList.length == 0) {
			props.options.checkStrictly ? (item.bx = 0, item.qx = 0) : ''
			return false
		}
		const i = checkList.findIndex(e => {
			return item[props.keyValue] == e[props.keyValue]
		}) > -1
		return i && !item.qx
	}
})
//到下一级
function toChildren(item) {
	if (!Boolean(item.children.length)) return
	uni.showLoading({
		title: '加载中'
	})
	let children = props.options.children;
	if (Boolean(item.children.length) && item[children].length > 0 && !(tree_stack.value[0][props.keyValue] == item[props.keyValue])) {
		tree.value = item[children];
		tree_stack.value.push(item);
	}
	nextTick(() => {
		uni.hideLoading()
		scrollLeft.value += 200;
	})
	if (props.options.checkStrictly) checkAllChoose();
}

function computAllNumber(arr) {
	for (let j = 0; j < arr.length; j++) {
		var e = arr[j];
		checkSum(e[props.keyValue])
		if (!Boolean(e.children.length)) {
			newNum.value++;
		} else {
			computAllNumber(e.children)
		}
	}
}

function checkSum(id) {
	for (let i = 0; i < newCheckList.value.length; i++) {
		if (id == newCheckList.value[i][props.keyValue]) {
			oldNum.value++;
			break
		}
	}
}

function checkAllChoose() {
	let o = false,
		t = true;
	tree.value.forEach((e, i) => {
		if (Boolean(e.children.length)) {
			e.qx = o;
			e.bx = o;
			computAllNumber(e.children);
			if (newNum.value != 0 && oldNum.value != 0) {
				if (newNum.value == oldNum.value) {
					e.qx = t;
					e.bx = o;
				} else {
					e.qx = o;
					e.bx = t;
				}
			}
			if (newNum.value != 0 && oldNum.value == 0) {
				tree.value[i].bx = o
				tree.value[i].qx = o
			}
			newNum.value = 0
			oldNum.value = 0
		}
	})
}

//单选
function checkbox(item, index) {
	const path = getPath()
	newCheckList.value = [{
		...item,
		path
	}]
}
// 获取路径
function getPath() {
	const path = [...tree_stack.value].map(e => {
		const item = Object.assign({}, e)
		delete item[props.options.children]
		return item
	})
	return path.slice(1, path.length) || []
}
// 取消下一级的选中
function getIdBydelete(arr) {
	arr.forEach(e => {
		if (!Boolean(e.children.length)) {
			for (var i = 0; i < newCheckList.value.length; i++) {
				if (e[props.keyValue] == newCheckList.value[i][props.keyValue]) {
					newCheckList.value.splice(i, 1)
					break;
				}
			}
		} else {
			getIdBydelete(e.children)
		}
	})
}

function checkboxChange(item, index, bx, qx) {
	const options = props.options
	if (!options.multiple) return;
	let findIdex = newCheckList.value.findIndex(e => item[props.keyValue] == e[props.keyValue]);
	const path = getPath();
	if (findIdex > -1) { //反选
		if (options.checkStrictly) { //关联子级
			if (!Boolean(e.children.length)) { //用户
				newCheckList.value.splice(findIdex, 1)
			} else { //非用户，取消所有下一级
				getIdBydelete(item.children)
			}
		} else {
			newCheckList.value.splice(findIdex, 1)
		}
	} else { //选中
		if (Boolean(item.children.length)&& options.checkStrictly) { //选中下一级
			if (qx || bx) { //取消下级
				getIdBydelete(item.children);
				item.qx = 0;
				item.bx = 0;
			} else {
				item.qx = 1;
				item.bx = 0;
				const {
					id,
					name,
				} = item
				const newObj = {
					id,
					name,
				}
				const pathList = tree_stack.value.length === 1 ? [newObj, ...path] : [...path, newObj]
				chooseChild(item.children, pathList);
			}
			return
		}
		newCheckList.value.push({
			...item,
			path
		});
	}
}
// 关联下一级,选中
function chooseChild(arr, path) {
	const oldPath = [...path]
	for (var i = 0, len = arr.length; i < len; i++) {
		let item = arr[i];
		if (!Boolean(item.children.length)) {
			newCheckList.value.push({
				...item,
				path: oldPath
			})
		} else {
			const newItem = {
				...item
			}
			delete newItem[props.options.children]
			const newPath = [...oldPath, newItem]
			chooseChild(item.children, newPath)
		}
	}
}
//搜索
const searchValue = ref('')
function confirmSearch() {
	searchResult.value = []
	searchTree(catchTreeNone, searchValue.value)
	isre.value = true
	tree_stack.value.splice(1, 1000)
	uni.showLoading({
		title: '正在查找'
	})
	setTimeout(() => {
		tree.value = searchResult.value
		uni.hideLoading()
	}, 300)
}

function searchTree(data, keyword) {
	let children = props.options.children;
	let label = props.options.label;
	for (var i = 0, len = data.length; i < len; i++) {
		if (data[i][label].indexOf(keyword) >= 0) {
			searchResult.value.push(data[i])
		}
		if (!data[i].user && data[i][children].length > 0) {
			searchTree(data[i][children], keyword)
		}
	}
}


//返回其它层
function backTree(item, index) {
	let max = 300;
	if (index === -1) {
		tree.value = catchTreeNone
		tree_stack.value.splice(1, max)
		console.log(tree.value)
		isre.value = false
	} else if (index === -2) { //搜索
		tree.value = searchResult.value
		tree_stack.value.splice(1, max)
	} else {
		if (tree_stack.value.length - index > 2) {
			tree_stack.value.splice(index + 1, max)
		} else if (index !== tree_stack.value.length - 1) {
			tree_stack.value.splice(tree_stack.value.length - 1, 1)
		}
		tree.value = item[props.options.children]
	}
	if (props.options.checkStrictly) checkAllChoose();
}

function backConfirm() {
	emit('sendValue', newCheckList.value)
}
const handleClick = (item, index) => {
	let children = item[props.options.children]
	if (index > -1 && children && children.length > 0) {
		toChildren(item)
	} else if (props.options.multiple) {
		checkboxChange(item, index, item.bx, item.qx)
	} else {
		checkbox(item, index)
	}
}
</script>
<style lang="scss" scoped>
@import './css/style.scss';
@import url("./css/icon.css");
</style>